/*
********************************************************************************
* Copyright (C) 2021, xiang.D <dx_65535@163.com>.
* All right reserved.
*
* File Name   : command.cc
* Author      :
* Version     : V1.0
* Description :
* Journal     : 2021-11-27 init v1.0
* Brief       : Blog: https://blog.csdn.net/qq_38750572?spm=1001.2014.3001.5343
* Others      :
                Compile command: g++ -Wl,--no-as-needed -std=c++11 command.cc
********************************************************************************
*/
#include <iostream>
#include <string>

using namespace std;

// 命令响应
class Receiver
{
public:
    explicit Receiver(string operation)
    {
        mOperation = operation;
    }

    void Action()
    {
        cout << mOperation << endl;
    }

private:
    string mOperation;
};

class Command
{
public:
    virtual ~Command()
    {

    }

    virtual void Execute() = 0;

protected:
    Command()
    {

    }
};

class LedCmd : public Command
{
public:
    void Execute()
    {
        if (NULL != mRcv) {
            this->mRcv->Action();
        }
    }

    explicit LedCmd(Receiver *pRcv)
    {
        if (NULL != pRcv) {
            mRcv = pRcv;
        }
        else
        {
            mRcv = NULL;
            cout << "Error: Param failed!" << endl;
        }
    }

private:
    Receiver *mRcv;
};

class MotorCmd : public Command
{
public:
    void Execute()
    {
        if (NULL != mRcv) {
            this->mRcv->Action();
        }
    }

    explicit MotorCmd(Receiver *pRcv)
    {
        if (NULL != pRcv) {
            mRcv = pRcv;
        }
        else
        {
            mRcv = NULL;
            cout << "Error: Param failed!" << endl;
        }
    }

private:
    Receiver *mRcv;
};

class Invoker
{
public:
    explicit Invoker(Command *pCmd)
    {
        if (NULL != pCmd)
        {
            mCmd = pCmd;
        }
        else
        {
            mCmd = NULL;
            cout << "Error: Param failed!" << endl;
        }
    }

    // 所有的命令响应动作都会经此接口触发, 可以在此处实现对命令的管理设计
    void Invoke()
    {
        if (NULL != mCmd) {
            mCmd->Execute();
        }
        else {
            cout << "Error: no action" << endl;
        }
    }

private:
    Command *mCmd;
};

int main(int argc, char *argv[])
{
    Receiver *theLedRcv = new Receiver("Led");
    LedCmd *theLedCmd = new LedCmd(theLedRcv);
    Invoker *theLedManager = new Invoker(theLedCmd);
    theLedManager->Invoke();

    Receiver *theMotorRcv = new Receiver("Motor");
    LedCmd *theMotorCmd = new LedCmd(theMotorRcv);
    Invoker *theMotorManager = new Invoker(theMotorCmd);
    theMotorManager->Invoke();

    delete theLedRcv;
    delete theLedCmd;
    delete theLedManager;

    delete theMotorRcv;
    delete theMotorCmd;
    delete theMotorManager;

    return 0;
}